#!coding:utf-8
# vim: tabstop=4 shiftwidth=4 softtabstop=4
"""
    @author jay.han
"""

import logging,os
import libvirt
from cvirt.common import utils,exception

LOG = logging.getLogger("tcloud.storage.pool")

MOUNT_POINT = '/opt/storage/'
DEFAULT_SCSI_TARGET = "/dev/disk/by-path"

class TcloudStoragePool(object):

    ISCSI = 'iscsi'
    NETFS = 'netfs'
    LOCAL = 'dir'
    FC = 'fc'

    _types = {
        ISCSI:'iSCSI Target',
        NETFS:'Network File System',
        LOCAL : 'local file disk',
        FC:'Fibre Channel'
    }

    def __init__(self, conn, name, type, target_path=None, uuid=None):
        if type not in TcloudStoragePool._types.keys():
            raise exception.Error("storage type %s is not supported:"
                                  % type)
        self._type = type
        self._name = name
        self._object_type = 'pool'
        self._conn = conn
        self._target_path = None

        self._format = None
        self._source_path = None


        if target_path is None:
            target_path = self._get_default_target_path()
        self.target_path = target_path

        if uuid:
            self.uuid = uuid
        else:
            self.uuid =utils.default_uuid()


    def ensure_default_mount(self):
        if not os.path.exists(self.target):
            os.makedirs(self.target)


    def escape(self,str):
        """Replaces chars ' " < > & with xml safe counterparts"""
        if str is None:
            return None

        str = str.replace("&", "&amp;")
        str = str.replace("'", "&apos;")
        str = str.replace("\"", "&quot;")
        str = str.replace("<", "&lt;")
        str = str.replace(">", "&gt;")
        return str



    def _get_target_xml(self):
        raise NotImplementedError()

    def _get_source_xml(self):
        raise NotImplementedError()

    def _get_storage_xml(self):
        src_xml = ""
        if self._get_source_xml() != "":
            src_xml = "  <source>\n" + \
                      "%s" % (self._get_source_xml()) + \
                      "  </source>\n"
        tar_xml = "  <target>\n" + \
                  "%s" % (self._get_target_xml()) + \
                  "  </target>\n"

        return "  <uuid>%s</uuid>\n" % self.uuid + \
               "%s" % src_xml + \
               "%s" % tar_xml


    def get_xml_template(self):

        root_xml = "<pool type='%s'>\n" % self._type

        xml = "%s" % root_xml + \
              """  <name>%s</name>\n""" % self._name + \
              """%(stor_xml)s""" % { "stor_xml" : self._get_storage_xml() } + \
              """</pool>\n"""
        return xml

    def create_pool(self,autostart=True):

        xml = self.get_xml_template()
        logging.debug("Creating storage pool '%s' with xml:\n%s",
                      self._name, xml)

        try:
            pool = self._conn.storagePoolDefineXML(xml, 0)
        except Exception, e:
            raise exception.Error("Could not define storage pool: %s" % str(e))


        errmsg = None

        try:
            pool.build(libvirt.VIR_STORAGE_POOL_BUILD_NEW)
            pool.create(0)
        except Exception, e:
            print e
            errmsg = "Error in create pool: %s" % str(e)
            LOG.debug(errmsg)

        if autostart and not errmsg:
            try:
                pool.setAutostart(True)
            except Exception, e:
                errmsg = "Could not set pool autostart flag: %s" % str(e)

        if errmsg:

            try:
                pool.undefine()
            except Exception, e:
                logging.debug("Error cleaning up pool after failure: " +
                              "%s" % str(e))
            raise exception.Error(errmsg)

        return pool



class NetworkFilesystemPool(TcloudStoragePool):

    formats = ["nfs", "glusterfs","cifs"]

    def __init__(self, conn, name, source_path=None, host=None,
                 target_path=None, format="nfs", uuid=None):
        TcloudStoragePool.__init__(self, name=name, type=TcloudStoragePool.NETFS,
                                   uuid=uuid, target_path=target_path, conn=conn)

        self.format = format

        if source_path:
            self.source_path = source_path
        if host:
            self.host = host

    def get_format(self):
        return self._format
    def set_format(self, val):
        if not val in self.formats:
            raise exception.error("Unknown Network Filesystem format: %s" % val)
        self._format = val
    format = property(get_format, set_format)

    def _get_default_target_path(self):
        path = (MOUNT_POINT + self._name)
        return path

    def _get_target_xml(self):
        xml = "    <path>%s</path>\n" % self.escape(self.target_path)
        return xml

    def _get_source_xml(self):
        xml = """    <format type="%s"/>\n""" % self.format + \
              """    <host name="%s"/>\n""" % self.host + \
              """    <dir path="%s"/>\n""" % self.escape(self.source_path)
        return xml


class LocalPool(TcloudStoragePool):
    """
    Create a local pool
    """


    def __init__(self, conn, name, target_path=None, uuid=None, perms=None):
        TcloudStoragePool.__init__(self, name=name, type=TcloudStoragePool.LOCAL,
                                   target_path=target_path, uuid=uuid, conn=conn)


    def _get_default_target_path(self):
        path = (MOUNT_POINT + self._name)
        return path

    def _get_target_xml(self):
        xml = "    <path>%s</path>\n" % self.escape(self.target_path)
        return xml

    def _get_source_xml(self):
        return ""

class ISCSIPool(TcloudStoragePool):
    """
    create a iscsi pool
    """

    def __init__(self, conn, name, source_path=None, host=None,
                 target_path=None, uuid=None):
        TcloudStoragePool.__init__(self, name=name, type=TcloudStoragePool.ISCSI,
                                   uuid=uuid, target_path=target_path, conn=conn)

        if source_path:
            self.source_path = source_path
        if host:
            self.host = host

        self._iqn = None

    def get_source_path(self):
        return self._source_path
    def set_source_path(self, val):
        self._source_path = val
    source_path = property(get_source_path, set_source_path)

    def _get_iqn(self):
        return self._iqn
    def _set_iqn(self, val):
        self._iqn = val
    iqn = property(_get_iqn, _set_iqn)

    def _get_default_target_path(self):
        return DEFAULT_SCSI_TARGET

    def _get_target_xml(self):
        xml = "    <path>%s</path>\n" % self.escape(self.target_path)
        return xml

    def _get_source_xml(self):

        iqn_xml = ""
        if self.iqn:
            iqn_xml += """    <initiator>\n"""
            iqn_xml += """      <iqn name="%s"/>\n""" % self.escape(self.iqn)
            iqn_xml += """    </initiator>\n"""

        xml  = """    <host name="%s"/>\n""" % self.host
        xml += """    <device path="%s"/>\n""" % self.escape(self.source_path)
        xml += iqn_xml

        return xml
if __name__ == '__main__':

    libvirt_uri = 'qemu:///system'
    auth = [[libvirt.VIR_CRED_AUTHNAME, libvirt.VIR_CRED_NOECHOPROMPT],
            'root',
            None]

    conn = libvirt.openAuth(libvirt_uri, auth, 0)
    print conn.listStoragePools()
    print conn.listDefinedStoragePools()
    print conn.storagePoolLookupByName('test-nfs').XMLDesc(0)

    # nfs_pool = NetworkFilesystemPool(conn=conn,name='test-nfs',source_path='/home/vmos/instances',host='172.16.10.245')
    #nfs_pool.get_pool_list(conn=conn,pool_type=TcloudStoragePool.NETFS,host='172.16.10.245')

